package com.peza.bikelog.business.convertor;

import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

import org.apache.log4j.Logger;

import com.peza.bikelog.common.domain.Bike;
import com.peza.bikelog.common.domain.CourseData;
import com.peza.bikelog.common.domain.FitnessData;
import com.peza.bikelog.common.domain.LogEntry;
import com.peza.bikelog.common.domain.SpeedData;
import com.peza.bikelog.common.domain.Surface;
import com.peza.bikelog.common.domain.TrainingZone;

public class CsvConverter {

	
	private static final String INPUT_FILE = "/Users/Peter/temp/traininglog.csv";
	
	private static Logger logger = Logger.getLogger("Converter.class");
	
	private static EntityManagerFactory emf = Persistence.createEntityManagerFactory("bikelog");
	private static EntityManager em = emf.createEntityManager();
	private static EntityTransaction tx = em.getTransaction();
	
	
	public static void main(String[] args) throws Exception {
		int counter = 0;
		int total = 0;
		
		try {
			// Open the file that is the first
			// command line parameter
			FileInputStream fstream = new FileInputStream(INPUT_FILE);
			// Get the object of DataInputStream
			DataInputStream in = new DataInputStream(fstream);
			BufferedReader br = new BufferedReader(new InputStreamReader(in));
			String strLine;

			// Read File Line By Line
			
			while ((strLine = br.readLine()) != null) {
				total++;
				while (strLine.contains(";;")){
					strLine = strLine.replace(";;", ";null;");
				}
				strLine = strLine.replace("#VERW!", "null");
				strLine = strLine.replace(",", ".");
				System.out.println(strLine);
				String[] fields = strLine.split(";");
				
				if (fields[1] != null){				
					try {
						GregorianCalendar time = new GregorianCalendar();
						
						DateFormat df = new SimpleDateFormat("E dd MMM yyyy");
						Date result =  df.parse(fields[1]); 
						
						
						time.setTime(result);
						
						String duration      = (!fields[2].equals("null")) ? fields[2] : "0";
						String location      = (!fields[3].equals("null")) ? fields[3] : "";
						String description   = (!fields[4].equals("null")) ? fields[4] : "";
						String surfaceString = (!fields[5].equals("null")) ? fields[5] : "";
						String bikeString    = (!fields[6].equals("null")) ? fields[6] : "";
						String zone			 = (!fields[7].equals("null")) ? fields[7] : "";
						String afstand  	 = (!fields[8].equals("null")) ? fields[8] : "0";
						String avs			 = (!fields[9].equals("null")) ? fields[9] : "0";
						String maxsp		 = (!fields[10].equals("null")) ? fields[10] : "0";
						String hm			 = (!fields[11].equals("null")) ? fields[11] : "0";
						String ahb			 = (!fields[12].equals("null")) ? fields[12] : "0";
						String mhb			 = (!fields[13].equals("null")) ? fields[13] : "0";
						String kcal			 = (!fields[14].equals("null")) ? fields[14] : "0";
						String rz			 = (!fields[15].equals("null")) ? fields[15] : "0";
						String hz			 = (!fields[16].equals("null")) ? fields[16] : "0";
						String fz			 = (!fields[17].equals("null")) ? fields[17] : "0";
						String pz			 = (!fields[18].equals("null")) ? fields[18] : "0";
						String mz			 = (!fields[19].equals("null")) ? fields[19] : "0";
						String avgPf		 = (!fields[21].equals("null")) ? fields[21] : "0";
						String avgWatt		 = (!fields[22].equals("null")) ? fields[22] : "0";

						tx.begin();
						

						Bike bike = getBike(bikeString);
						TrainingZone tz = getZone(zone);
						
						try {
							LogEntry le = new LogEntry();
							SpeedData speed = new SpeedData();
							FitnessData fitness = new FitnessData();
							CourseData course = new CourseData();
							
							speed.setAveragePedalFreq(convertToInteger(avgPf));
							speed.setAverageSpeed(convertToFloat(avs));
							speed.setAverageWatts(convertToInteger(avgWatt));
							speed.setMaxSpeed(convertToFloat(maxsp));
							speed.setDuration(convertToInteger(duration));
							
							fitness.setAverageHr(convertToInteger(ahb));
							fitness.setMaxHr(convertToInteger(mhb));
							fitness.setRecPct(convertToInteger(rz));
							fitness.setD1Pct(convertToInteger(hz));
							fitness.setD2Pct(convertToInteger(fz));
							fitness.setD3Pct(convertToInteger(pz));
							fitness.setMaxPct(convertToInteger(mz));
							fitness.setZone(tz);
							fitness.setKcal(convertToInteger(kcal));
							
							course.setDistance(convertToFloat(afstand));
							course.setAscent(convertToInteger(hm));
							course.setLocation(location);
							course.setSurface(getSurface(surfaceString));
							
							le.setDate(time);
							le.setCourse(course);
							le.setDescription(description);
							le.setBike(bike);
							le.setSpeed(speed);
							le.setFitnessData(fitness);
							le.setComments("");
							le.setPolarFile(null);
							
							logger.debug(le);
							
							em.persist(le);
									
							counter++;			
						}
						catch (IllegalArgumentException e2) {
							e2.printStackTrace();
						}
						finally {
							tx.commit();
						}	
					}
					catch (IllegalArgumentException e){
						e.printStackTrace();
						System.out.println("illegal argument");
					} catch (Exception e){
						e.printStackTrace();
						System.out.println("error");
					}
					
				}
				else {
					System.out.println("null");
				}
			}
			em.close();
			
			// Close the input stream
			in.close();
	
		} catch (IOException e) {// Catch exception if any
			System.err.println("Error: " + e.getMessage());
			throw e;
		}
		
		System.out.println("Performed " + counter + "/" + total+ " conversions ");
		
	}

	
	private static Float convertToFloat(String input){
		return Float.parseFloat(input);
	}
	
	private static Integer convertToInteger (String input){
		Integer output = null;
		try {
			output = Integer.parseInt(input);
		} catch (NumberFormatException e) {
			output = 0;
		}
		return output;
	}
	
	
	private static TrainingZone getZone(String zone) {
		logger.debug("ZONE = " + zone);
		if (zone.contains("D1")){
			return TrainingZone.D1;
		}
		else if (zone.contains("D2")){
			return TrainingZone.D2;
		}
		else if (zone.contains("D2")){
			return TrainingZone.D2_INTS;
		}
		else if (zone.equals("D3")){
			return TrainingZone.D3;
		}
		else if (zone.contains("D3_INTS")){
			return TrainingZone.D3_INTS;
		}
		else if (zone.contains("F")){
			return TrainingZone.FORCE;
		}
		else if (zone.contains("HS")){
			return TrainingZone.HILL_SPRINTS;
		}
		else if (zone.contains("MAX")){
			return TrainingZone.MAX;
		}
		else if (zone.contains("MAX_INTS")){
			return TrainingZone.MAX_INTS;
		}
		else if (zone.contains("MIX")){
			return TrainingZone.MIX;
		}
		else if (zone.contains("REC")){
			return TrainingZone.REC;
		}
		else if (zone.contains("XC")){
			return TrainingZone.XC;
		}
		else if (zone.contains("RAC")){
			return TrainingZone.XC;
		}
		else if (zone.contains("TT")){
			return TrainingZone.XC;
		}
		else if (zone.contains("Marathon")){
			return TrainingZone.XC;
		}
		
		return TrainingZone.UNDEFINED;
	}

	private static Bike getBike(String bikeString) {
		
		if (bikeString.contains("Trek")){
			return Bike.TREK;
		}
		else if (bikeString.contains("Kona")){
			return Bike.KONA;
		}
		else if (bikeString.contains("Crux")){
			return Bike.SPECIALIZED_CRUX;
		}
		else if (bikeString.equals("Specialized")){
			return Bike.SPECIALIZED_FSR;
		}
		else if (bikeString.contains("SWORKS")){
			return Bike.SPECIALIZED_SWORKS;
		}
		else if (bikeString.contains("Granville Race")){
			return Bike.GRANVILLE_RACE;
		}
		else if (bikeString.contains("Zwart")){
			return Bike.GRANVILLE_EVO_B;
		}
		else if (bikeString.contains("Zilver")){
			return Bike.GRANVILLE_EVO_S;
		}
		else if (bikeString.contains("Canyon")){
			return Bike.CANYON;
		}
		else if (bikeString.contains("Decathlon")){
			return Bike.DECATHLON;
		}
		else if (bikeString.contains("Cleveland")){
			return Bike.CLEVELAND;
		}
		else if (bikeString.contains("Schwinn")){
			return Bike.SCHWINN;
		}
		else if (bikeString.contains("Columbus")){
			return Bike.COLUMBUS;
		}
		
		return Bike.OTHER;
	}
	
	
	private static Surface getSurface(String sin){
		
		if (sin.contains("M")){
			return Surface.OFFROAD;
		}
		else if (sin.contains("W")){
			return Surface.ROAD;
		}
		else if (sin.contains("R")){
			return Surface.INDOOR;
		}
		else if (sin.contains("T")){
			return Surface.TRAILER;
		}
		else {
			return Surface.UNKNOWN;
		}
		
	}
	

}
